﻿using System;
using System.CodeDom;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ShaoLuWinFormsApp
{
    public delegate int DelegateEepromPageReadHandle(byte[] PageData);
    public delegate int DelegateEepromPageWriteHandle(byte[] PageData);
    internal class EepromFileIoControl
    {
        DelegateEepromPageReadHandle EepromPageReadHandle;
        DelegateEepromPageWriteHandle EepromPageWriteHandle;
        

        public enum e_EepromDataStatus : byte {UNINIT_DATA=0x00, READ_FROM_CHIP, GENERATE_BY_SOFTWARE};
        public enum e_EepromMessageGetType : byte { SERIAL_NUMBER=0x00, USER_DATA, QC_DATA, INPUT_OPERATOR};
        // 数据区
        byte[] EepromData = new byte[2048];
        // 状态
        e_EepromDataStatus EepromDataStatus = e_EepromDataStatus.UNINIT_DATA;
        public EepromFileIoControl()
        {
            EepromDataStatus = e_EepromDataStatus.UNINIT_DATA;
        }

        ~EepromFileIoControl()
        {

        }
        public bool EepromFileGenerate()
        {
            // 利用程序生成
            Random random = new Random();
            random.NextBytes(EepromData);
            ushort offset = 0;
            do
            {
                EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset] = EepromFileDefintions.SERIAL_NUMBER_F[offset];
                offset++;
            } while (offset < 10);
            EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset++] = (byte)DateTime.Now.Year;
            EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset++] = (byte)DateTime.Now.Month;
            EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset++] = (byte)DateTime.Now.Day;
            EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset++] = (byte)DateTime.Now.Hour;
            EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset++] = (byte)DateTime.Now.Minute;
            EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset++] = (byte)DateTime.Now.Second;
            // 用户区清空
            for(int i=0;i<16;i++)
            {
                EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset + i] = 0;
            }
            // todo log 生成成功

            EepromDataStatus = e_EepromDataStatus.GENERATE_BY_SOFTWARE;
            return true;
        }

        public bool EepromFileInsertSerialNumber(byte[] SerialNumber)
        {
            ushort offset = 0;
            if (EepromDataStatus == e_EepromDataStatus.UNINIT_DATA) return false;
            if (SerialNumber.Length != 16) return false;

            do
            {
                EepromData[EepromFileDefintions.TIPMODULE_MESSAGE_ADDR + offset] = SerialNumber[offset];
                offset++;
            } while (offset < SerialNumber.Length);

            return true;
        }
        public byte[] EepromFileMessageGet(e_EepromMessageGetType GetType)
        {
            byte[] array_data = null;
            switch (GetType)
            {
                case e_EepromMessageGetType.SERIAL_NUMBER:
                    array_data = new byte[16];
                    break;
                case e_EepromMessageGetType.USER_DATA:
                    array_data = new byte[16];
                    break;
                case e_EepromMessageGetType.QC_DATA:
                    array_data = new byte[16];
                    break;
                case e_EepromMessageGetType.INPUT_OPERATOR:
                    array_data = new byte[16];
                    break;
            }
            
            return array_data;
        }
        // 插入质检时间戳与工号
        public bool EepromFileInsertQualityInspectionTimestamp(byte[] QualityInspectionMessage)
        {
            ushort offset = 0;
            if (EepromDataStatus == e_EepromDataStatus.UNINIT_DATA) return false;
            if (QualityInspectionMessage.Length != 16) return false;

            do
            {
                EepromData[EepromFileDefintions.TIPMODULE_QC_ADDR + offset] = QualityInspectionMessage[offset];
                offset++;
            } while (offset < 16);
            return true;
        }

        public bool EepromFileInsertInputOperator(byte[] InputOperator)
        {
            ushort offset = 0;
            if (EepromDataStatus == e_EepromDataStatus.UNINIT_DATA) return false;
            if (InputOperator.Length != 16) return false;

            do
            {
                EepromData[EepromFileDefintions.TIPMODULE_INPUTOPERATOR + offset] = InputOperator[offset];
                offset++;
            } while (offset < 16);
            return true;
        }
       

        byte[] EepromWriteOperation(byte[] binfile, byte sendpage, bool isPageWrite)
        {
            byte[] SendDataPackage = new byte[22];
            SendDataPackage[0] = EepromFileDefintions.PACKAGE_HEAD0;
            SendDataPackage[1] = EepromFileDefintions.PACKAGE_HEAD1;
            if (isPageWrite == true)
                SendDataPackage[2] = EepromFileDefintions.COMM_WRITE_PAGE;
            else
                SendDataPackage[2] = EepromFileDefintions.COMM_WRITE_CONTINUTE;
            SendDataPackage[3] = sendpage;     // page

            Array.Copy(binfile, sendpage * 16, SendDataPackage, 4, 16);
            // 计算crc
            UInt16 crc16 = System_crc16(SendDataPackage, 20);
            byte[] crcdata = BitConverter.GetBytes(crc16);
            SendDataPackage[20] = crcdata[1];
            SendDataPackage[21] = crcdata[0];

            // 串口发送接口
            return SendDataPackage;
        }

        byte[] EepromReadOperation(byte ReceivePage, bool isPageRead)
        {
            byte[] SendDataPackage = new byte[7];
            SendDataPackage[0] = EepromFileDefintions.PACKAGE_HEAD0;
            SendDataPackage[1] = EepromFileDefintions.PACKAGE_HEAD1;
            if (isPageRead == true)
                SendDataPackage[2] = EepromFileDefintions.COMM_READ_PAGE;
            else
                SendDataPackage[2] = EepromFileDefintions.COMM_READ_CONTINUTE;
            SendDataPackage[3] = ReceivePage;

            SendDataPackage[4] = 0;
            UInt16 crc16 = System_crc16(SendDataPackage, 5);
            byte[] crcdata = BitConverter.GetBytes((UInt16)crc16);
            SendDataPackage[5] = crcdata[0];
            SendDataPackage[6] = crcdata[1];

            return SendDataPackage;
        }

        bool EepromReadHandle(byte[] GetReceivePackage, ushort Length)
        {
            ushort crc16 = System_crc16(GetReceivePackage, (ushort)(Length - 2));
            byte[] crcdata = BitConverter.GetBytes(crc16);

            // CRC16校验
            if ((crcdata[0] == GetReceivePackage[Length - 1]) && (crcdata[1] == GetReceivePackage[Length - 2]))
            {
                // 判断功能码
                if (GetReceivePackage[2] == EepromFileDefintions.COMM_WRITE_CONTINUTE)
                {
                    // 写入成功
                    if (GetReceivePackage[4] == 0x01)
                    {
                        byte sendpage = GetReceivePackage[3];
                        if (sendpage < 0x7f)
                        {
                            sendpage++;
                            EepromWriteOperation(EepromData, sendpage, false);
                            // todo log 当前发送页是sendpage
                        }
                        else
                        {
                            // todo log 发送完成
                        }
                    }
                }
                else if (GetReceivePackage[2] == EepromFileDefintions.COMM_READ_CONTINUTE)
                {
                    byte receivedpage = GetReceivePackage[3];
                    if(Length == 22)
                    {
                        Array.Copy(GetReceivePackage, 4, EepromData, receivedpage * 16, 16);
                        if (receivedpage < 0x7f)
                        {
                            
                            receivedpage++;
                            EepromReadOperation(receivedpage, false);
                            // todo log 打印已接收的页码
                        }
                        else
                        {
                            // todo log 全部接收完成
                        }
                    }
                    else
                    {
                        // todo log 从机读取失败
                    }
                }
                else if (GetReceivePackage[2] == EepromFileDefintions.COMM_READ_PAGE)
                {
                    EepromPageReadHandle(GetReceivePackage);
                }
                else if (GetReceivePackage[2] == EepromFileDefintions.COMM_WRITE_PAGE)
                {
                    EepromPageWriteHandle(GetReceivePackage);
                }
            }

            return true;

        }

        public void SetDelegatePageReadHandle(DelegateEepromPageReadHandle Delegate) 
        {
            this.EepromPageReadHandle = Delegate;
        }
        public void SetDelegatePageWriteHandle(DelegateEepromPageWriteHandle Delegate)
        {
            this.EepromPageWriteHandle = Delegate;
        }

        public ushort System_crc16(byte[] puchMsg, ushort hwDataLen)
        {
            byte uchCRCHi = 0xFF; // CRC 的高字节初始化
            byte uchCRCLo = 0xFF; // CRC 的低字节初始化
            byte index; // CRC 查询表索引
            byte Counter = 0;
            //完成整个报文缓冲区
            for (Counter = (byte)hwDataLen; Counter > 0; Counter--)
            {
                index = (byte)(uchCRCLo ^ puchMsg[0]); // 计算 CRC
                uchCRCLo = (byte)(uchCRCHi ^ EepromFileDefintions.System_crcH[index]);
                uchCRCHi = EepromFileDefintions.System_crcL[index];
                puchMsg = puchMsg.Skip(1).ToArray();
            }
            return (ushort)(uchCRCHi << 8 | uchCRCLo);
        }
    }
}
